package com.bolingcavalry.crm.user.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.base.PageResult;
import com.bolingcavalry.crm.security.utils.SecurityUtils;
import com.bolingcavalry.crm.user.domain.Login;
import com.bolingcavalry.crm.user.service.UserService;
import com.bolingcavalry.crm.user.util.JwtUtil;
import com.dto.*;
import com.dto.WxResponse;
import com.dto.user.UserDTO;
import com.dto.user.UserRoleListDto;
import com.entity.user.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vo.*;
import com.vo.user.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.ApiOperation;
import com.base.ResponseResult;
import org.springframework.web.client.RestTemplate;

import java.util.*;

@RestController
@RequestMapping("/auth")
public class LoginController {

    @Value("${weixin.appid}")
    private String appId;

    @Value("${weixin.secret}")
    private String secret;

    @Autowired
    private UserService userService;

    @Autowired
    private JwtUtil jwtUtil;


    /**
     * 登录接口
     * @param login
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "登录")
    public ResponseResult<Map<String, Object>> login(@RequestBody Login login){
        ResponseResult<Map<String, Object>> result =userService.login(login);
        return result;
    }


    /**
     * 微信登录接口
     */
    @PostMapping("/wxlogin")
    public ResponseResult<Map<String, Object>> wxLogin(@RequestBody Map<String, String> params) {
        String code = params.get("code");
        if (code == null || code.trim().isEmpty()) {
            return ResponseResult.error("code 不能为空");
        }

        try {
            // 1. 调用微信接口获取 openid
            WxResponse wxResponse = getOpenIdFromWeChat(code);
            // 正确处理微信返回结果
            if (wxResponse.getErrcode() != null && wxResponse.getErrcode() != 0) {
                return ResponseResult.error("微信登录失败: " + wxResponse.getErrmsg());
            }
            String openid = wxResponse.getOpenid();
            System.out.println("获取到 openid: " + openid);

            // 2. 根据 openid 查询用户
            User user = userService.findByOpenId(openid);

            if (user != null) {
                // 用户已绑定，执行登录逻辑
                return handleUserLogin(user);
            } else {
                // 用户未绑定，返回 openid，前端跳转绑定页
                Map<String, Object> data = new HashMap<>();
                data.put("openid", openid);
                data.put("isBound", false);
                return ResponseResult.success(data);
            }

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseResult.error("服务器内部错误");
        }
    }

    // 处理已绑定用户的登录逻辑（复用你的权限 + JWT 生成）
    private ResponseResult<Map<String, Object>> handleUserLogin(User user) {
        String username = user.getUsername();

        // 1. 获取用户角色（List<String>）
        List<String> role = userService.getRole(username);
        if (role == null || role.isEmpty()) {
            role = List.of("USER"); // 默认角色
        }

        // 2. 获取权限名称列表
        List<String> permissionsName = new ArrayList<>();
        for (String roleName : role) {
            Long roleId = userService.getRoleIdByRoleName(roleName);
            if (roleId != null) {
                List<PermissionVO> permissions = userService.getPermissionsByRoleId(roleId);
                if (permissions != null) {
                    for (PermissionVO p : permissions) {
                        if (p.getPermissionName() != null) {
                            permissionsName.add(p.getPermissionName());
                        }
                    }
                }
            }
        }

        // 3. 构建权限对象（使用 AuthorityUtils，和你原来一致）
        String[] rolesArray = role.toArray(new String[0]);
        var authorities = AuthorityUtils.createAuthorityList(rolesArray);

        // 4. 创建认证对象（不设置 details，和你原始 login 一致）
        UsernamePasswordAuthenticationToken authentication =
                new UsernamePasswordAuthenticationToken(username, null, authorities);

        // 5. 设置到 SecurityContext
        SecurityContextHolder.getContext().setAuthentication(authentication);

        // 6. 生成 JWT Token（复用你的 jwtUtil）
        String token = jwtUtil.createToken(username, role, permissionsName);

        // 7. 封装返回数据
        Map<String, Object> data = new HashMap<>();
        data.put("token", token);
        data.put("username", username);
        data.put("role", role);
        data.put("permissions", permissionsName);
        data.put("openid", user.getOpenid());

        return ResponseResult.success(data);
    }

    // 调用微信接口
    private WxResponse getOpenIdFromWeChat(String code) throws Exception {
        String url = "https://api.weixin.qq.com/sns/jscode2session" +
                "?appid=" + appId +
                "&secret=" + secret +
                "&js_code=" + code +
                "&grant_type=authorization_code";
        System.out.println("🔗 请求微信的 URL: " + url);

        // 使用 RestTemplate 发送请求
        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(url, String.class);
        System.out.println("📨 微信响应: " + response);

        // 使用 ObjectMapper 解析响应
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(response, WxResponse.class);
    }


    /**
     * openid绑定账号接口
     */
    @PostMapping("/bind")
    @ApiOperation(value = "openid绑定账号")
    public ResponseResult<String> bind(@RequestBody UserDTO user){
        //拿到用户信息插入数据库
        ResponseResult<String> openidbind = userService.openidbind(user);
        return openidbind;
    }

    /**
     * 注册接口
     * @param user
     * @return
     */
    @PostMapping("/registered")
    @ApiOperation(value = "注册")
    public ResponseResult<String> registered(@RequestBody UserDTO user){
        //密码加密
        user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
        //拿到用户信息插入数据库
        Boolean b = userService.insect(user);
        if (!b){
            return ResponseResult.error("注册失败，用户已存在");
        }
        return ResponseResult.success("注册成功",user.getUsername());
    }

    /**
     * 查询角色名+id以便注册调用
     */
    @GetMapping("/getRoleAndId")
    @ApiOperation(value = "查询全部角色ID和名称")
    public ResponseResult<List<RoleVO>> getRoleAndId() {
        return ResponseResult.success(userService.getRoleAndId());
    }

    /**
     * 添加角色接口
     */
    @PostMapping("/addRole")
    @ApiOperation(value = "添加角色")
    public ResponseResult<String> addRole(@RequestBody RoleDTO roleDTO){
        Boolean aBoolean =userService.addRole(roleDTO);
        if(!aBoolean)
            return ResponseResult.error("添加角色失败");
        return ResponseResult.success("添加角色成功");
    }

    /**
     * 添加权限接口
     */
    @PostMapping("/addPermission")
    @ApiOperation(value = "为角色名添加权限")
    public ResponseResult<String> addPermission(@RequestBody PermissionDTO PermissionDTO){
        userService.addPermission(PermissionDTO);
        return ResponseResult.success("添加权限成功");
    }

    /**
     * 查询角色权限接口，以便新增的时候获取
     */
    @GetMapping("/getPermissions")
    @ApiOperation(value = "根据角色名查询角色权限")
    public ResponseResult<List<PermissionVO>> getPermissions(@RequestParam String roleName){
        //根据名称获取角色id
        Long roleId = userService.getRoleIdByRoleName(roleName);
        //查询权限
        List<PermissionVO> permissionsByRoleId = userService.getPermissionsByRoleId(roleId);
        return ResponseResult.success(permissionsByRoleId);
    }


    /**
     * 验证用户名密码
     * @param username
     * @param password
     * @return
     */
    private boolean authenticate(String username, String password) {
        String hashpw= userService.getPassword(username);
        //密码解密，校验
        if (BCrypt.checkpw(password, hashpw)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 查询用户当前状态 服务出差中 在岗办公中 公务外出中
     * 查询全部用户的状态，展示状态栏信息
     * 点击进入后根据那些状态分页查询用户信息
     * UserStatusVO 封装了状态名和数量
     */
    @GetMapping("/getUserStatus")
    @ApiOperation(value = "查询用户当前状态")
    public ResponseResult<List<UserStatusVO>> getUserStatus() {
        return ResponseResult.success(userService.getUserStatus());
    }


    /**
     * 用户分页查询
     * 状态、登录用户名（username）、姓名（nickname）
     */
    @GetMapping("/getUserByPage")
    @ApiOperation(value = "用户分页查询")
    public ResponseResult<IPage<UserDTO>> getUserByPage(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(required = false) Integer pageSize,
            @RequestParam(required = false) String status,
            @RequestParam(required = false) String username,
            @RequestParam(required = false) String nickname
    ){
        IPage<UserDTO> page = userService.getByConditions(pageNum, pageSize,status,username,nickname);
        PageResult<UserDTO> result = new PageResult<>();
        result.setTotal(page.getTotal());
        result.setPages((int) page.getPages());
        result.setCurrent((int) page.getCurrent());
        result.setSize((int) page.getSize());
        result.setRecords(page.getRecords());
        return ResponseResult.success("查询成功",result);
    }

    // 修改用户
    @PostMapping("/update")
    @ApiOperation(value = "修改用户信息（管理端）")
    public ResponseResult<String> updateAdmin(@RequestBody UserDTO userDTO) {
        Boolean success = userService.update(userDTO);
        if (!success) {
            return ResponseResult.error("修改失败，请确认用户是否存在");
        }
        return ResponseResult.success("修改成功");
    }

    // 删除用户
    @DeleteMapping("/delete/{id}")
    @ApiOperation(value = "删除用户")
    public ResponseResult<String> deleteUser(@PathVariable Long id) {
        Boolean success = userService.deleteById(id);
        if (!success) {
            return ResponseResult.error("删除失败，请确认用户是否存在");
        }
        return ResponseResult.success("删除成功");
    }

    //get查询详细
    @GetMapping("/get/{id}")
    @ApiOperation(value = "根据id查询用户详细信息")
    public ResponseResult<UserDTO> getUser(@PathVariable Long id) {
        UserDTO userVO = userService.getUserById(id);
        if (userVO == null) {
            return ResponseResult.error("用户不存在");
        }
        return ResponseResult.success("查询成功", userVO);
    }

    //获取员工状态数量count（服务外出、在岗办公、公务外出）
    @GetMapping("/count")
    @ApiOperation(value = "查询用户当前状态总数")
    public ResponseResult<UserStatusCountVO> getUserStatusCount() {
        return ResponseResult.success(userService.getUserStatusCount());
    }

    //修改用户
    @PostMapping("/userupdate")
    @ApiOperation(value = "修改用户信息（个人端）")
    public ResponseResult<String> updateUser(@RequestBody UserDTO userDTO) {
        return (userService.userupdate(userDTO)?ResponseResult.success("修改成功"):ResponseResult.error("修改失败"));
    }

    //接收小程序端发送的openid校验是否绑定账号信息
    @PostMapping("/checkOpenid")
    @ApiOperation(value = "校验小程序端发送的openid")
    public ResponseResult<Map<String, Object>> checkOpenid(@RequestParam String openid) {
        User user =userService.checkOpenid(openid);
        if(user!=null){
            //如果数据库中存在openid则直接调用登录接口返回 token
            return userService.wxtoken(user.getUsername());
        }else {
            return ResponseResult.error("未绑定账号请先绑定账号");
        }
    }

    //openid绑定账号
    @PostMapping("/openidbind")
    @ApiOperation(value = "小程序端绑定账号")
    public ResponseResult<String> openidbind(@RequestBody UserDTO userDTO) {
        return userService.openidbind(userDTO);
    }


    //查询当前用户信息
    @GetMapping("/me")
    public ResponseResult<UserVO> getAuthenticatedUser() {
        //获取当前登录用户名
        String username = SecurityUtils.getCurrentUsername();
        //根据用户名获取角色信息
        UserVO userVO =userService.getUserVO(username);
        return ResponseResult.success(userVO);
    }

    //修改密码个人端
    @PostMapping("/updatepassword")
    @ApiOperation(value = "修改密码个人端")
    public ResponseResult<String> updatePassword(@RequestBody PasswordDTO passwordDTO) {
        return userService.updatePassword(passwordDTO);
    }

    //查询用户列表
    @PostMapping("/getUserList")
    @ApiOperation(value = "查询用户列表")
    public ResponseResult<List<UserRoleListVo>> getUserList(@RequestBody(required = false) UserRoleListDto roleNames) {
        List<UserRoleListVo> userVOList = userService.getUserList(roleNames);
        return ResponseResult.success(userVOList);
    }

    //查询全部用户列表数组
    @GetMapping("/getAllUserList")
    @ApiOperation(value = "查询全部用户列表")
    public ResponseResult<List<String>> getAllUserList(@RequestParam(required = false) String nickName) {
        List<String> userVOList = userService.getAllUserList(nickName);
        return ResponseResult.success(userVOList);
    }

    //根据状态查询员工列表
    @GetMapping("/getUserListByStatus")
    @ApiOperation(value = "根据状态查询员工列表")
    public ResponseResult<List<UserlocationVO>> getUserListByStatus(@RequestParam String status) {
        List<UserlocationVO> userVOList = userService.getUserListByStatus(status);
        return ResponseResult.success(userVOList);
    }

    @PostMapping("/test")
    public void test(@RequestBody JSONObject jsonObject) {
        System.out.println(jsonObject.toJSONString());
    }

}


